﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using douban.Core.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace douban.Core.Apis
{

    public class Topic
    {
        [JsonProperty("updated")]
        public DateTime Updated { get; set; }

        [JsonProperty("like_count")]
        public int LikeCount { get; set; }

        [JsonProperty("alt")]
        public string Alt { get; set; }

        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("locked")]
        public bool Locked { get; set; }

        [JsonProperty("title")]
        public string Title { get; set; }

        [JsonProperty("share_url")]
        public string ShareUrl { get; set; }

        [JsonProperty("created")]
        public DateTime Created { get; set; }

        [JsonProperty("content")]
        public string Content { get; set; }

        public string ContentHtml
        {
            get
            {
                Regex regex = new Regex(@"<图片\d+>");

                if (string.IsNullOrEmpty(Content)) return string.Empty;
                var contentHtml = Content.Replace("\r\n", "</br>");

                var photos = Photos.ToList();
                contentHtml = regex.Replace(contentHtml, match =>
                {
                    int index = int.Parse(match.Value.Replace("<图片", "").TrimEnd('>'));

                    if (index < photos.Count && index > 0)
                    {
                        var photo = photos[index - 1];
                        photos.Remove(photo);
                        if (photo != null)
                        {
                           return $"<img  src='{photo.Alt}'  alt='{photo.Title}' />";
                        }
                    }
                    return "";
                });
                string images = "";  //剩余的照片
                if (Photos.Any())
                {
                    images = string.Join("</br>", photos.Select(photo => $"<img  src='{photo.Alt}'  alt='{photo.Title}' />"));
                }
                
                return $"<html><head><meta charset='UTF-8'><style>body, html{{overflow-x:hidden;    line-height: 1.8!important;}} img{{width:100%;display: block;display: block;}}</style></head> {contentHtml}</br>{images}</html>";
            }
        }

        [JsonProperty("comments_count")]
        public int CommentsCount { get; set; }

        [JsonProperty("author")]
        public User Author { get; set; }

        [JsonProperty("group")]
        public Group Group { get; set; }

        [JsonProperty("photos")]
        public List<Photo> Photos { get; set; }

        public string UpdatedDescription => DateTimeUtil.Description(Updated);
    }

    public class Group
    {
        [JsonProperty("domain")]
        public string Domain { get; set; }

        [JsonProperty("uid")]
        public string Uid { get; set; }

        [JsonProperty("member_role")]
        public string MemberRole { get; set; }

        [JsonProperty("owner")]
        public User Owner { get; set; }

        [JsonProperty("admins")]
        public List<User> Admins { get; set; }

        [JsonProperty("alt")]
        public string Alt { get; set; }

        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("name")]
        public string Name { get; set; }

        [JsonProperty("desc")]
        public string Description { get; set; }

        [JsonProperty("member_count")]
        public int MemberCount { get; set; }

        [JsonProperty("created")]
        public DateTime Created { get; set; }

        [JsonProperty("join_type")]
        public string JoinType { get; set; }

        [JsonProperty("admin_role_name")]
        public string AdminRoleName { get; set; }

        [JsonProperty("member_role_name")]
        public string MemberRoleName { get; set; }

        [JsonProperty("large_avatar")]
        public string LargeAvatar { get; set; }

        [JsonProperty("avatar")]
        public string Avatar { get; set; }
    }

    public class PhotoSize
    {
        [JsonProperty("width")]
        public int Width { get; set; }

        [JsonProperty("height")]
        public int Height { get; set; }
    }

    public class Photo
    {
        [JsonProperty("size")]
        public PhotoSize Size { get; set; }

        [JsonProperty("alt")]
        public string Alt { get; set; }

        [JsonProperty("layout")]
        public string Layout { get; set; }

        [JsonProperty("topic_id")]
        public string TopicId { get; set; }

        [JsonProperty("seq_id")]
        public string SeqId { get; set; }

        [JsonProperty("author_id")]
        public string AuthorId { get; set; }

        [JsonProperty("title")]
        public string Title { get; set; }

        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("creation_date")]
        public DateTime CreationDate { get; set; }
    }

    public class Comment
    {
        [JsonProperty("text")]
        public string Text { get; set; }

        [JsonProperty("vote_count")]
        public int VoteCount { get; set; }

        [JsonProperty("author")]
        public User Author { get; set; }

        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("time")]
        public DateTime Time { get; set; }

        [JsonProperty("ispopular")]
        public bool IsPopular { get; set; }

        [JsonProperty("quote_comment")]
        public Comment QuoteComment { get; set; }


        public string CreatedDescription
        {
            get { return DateTimeUtil.Description(Time); }
        }
        //public string CreatedDescription
        //{
        //    get
        //    {
        //        var span = DateTime.Now.Subtract(Time);

        //        if (span.TotalDays > 1)
        //        {
        //            return string.Format("{0:F0}日前", span.TotalDays);
        //        }
        //        if (span.TotalHours > 1)
        //        {
        //            return string.Format("{0:F0}小时前", span.TotalHours);
        //        }
        //        if (span.TotalMinutes > 1)
        //        {
        //            return string.Format("{0:F0}分钟前", span.TotalMinutes);
        //        }
        //        if (span.TotalSeconds > 30)
        //        {
        //            return string.Format("{0:F0}秒前", span.TotalSeconds);
        //        }
        //        return "刚刚";
        //    }
        //}
    }

    public static partial class Api
    {
        private const string AllGroupsUrl = "/v2/group/channels/all/groups";
        private const string CultureGroupsUrl = "/v2/group/channels/culture/topics";
        private const string TravelGroupsUrl = "/v2/group/channels/travel/topics";
        private const string EntGroupsUrl = "/v2/group/channels/ent/topics";
        private const string FashionGroupsUrl = "/v2/group/channels/fashion/topics";
        private const string LifeGroupsUrl = "/v2/group/channels/life/topics";
        private const string TechGroupsUrl = "/v2/group/channels/tech/topics";

        private const string AllTopicsUrl = "/v2/group/channels/all/topics";
        private const string CultureTopicsUrl = "/v2/group/channels/culture/topics";
        private const string TravelTopicsUrl = "/v2/group/channels/travel/topics";
        private const string EntTopicsUrl = "/v2/group/channels/ent/topics";
        private const string FashionTopicsUrl = "/v2/group/channels/fashion/topics";
        private const string LifeTopicsUrl = "/v2/group/channels/life/topics";
        private const string TechTopicsUrl = "/v2/group/channels/tech/topics";
        private const string MyTopicsUrl = "/v2/group/user_topics";

        private const string TopicCommentsUrl = "/v2/group/topic/{0}/comments";

        public static async Task<IEnumerable<Topic>> GpSearchExploreTopics(int start = 0, int count = 20)
        {
            return await GpSearchTopics(AllTopicsUrl,start,count);
        }

        public static async Task<IEnumerable<Topic>> GpSearchCultureTopics(int start = 0, int count = 20)
        {
            return await GpSearchTopics(CultureTopicsUrl, start, count);
        }

        public static async Task<IEnumerable<Topic>> GpSearchTravelTopics(int start = 0, int count = 20)
        {
            return await GpSearchTopics(TravelTopicsUrl, start, count);
        }

        public static async Task<IEnumerable<Topic>> GpSearchEntTopics(int start = 0, int count = 20)
        {
            return await GpSearchTopics(EntTopicsUrl, start, count);
        }

        public static async Task<IEnumerable<Topic>> GpSearchFashionTopics(int start = 0, int count = 20)
        {
            return await GpSearchTopics(FashionTopicsUrl, start, count);
        }

        public static async Task<IEnumerable<Topic>> GpSearchLifeTopics(int start = 0, int count = 20)
        {
            return await GpSearchTopics(LifeTopicsUrl, start, count);
        }

        public static async Task<IEnumerable<Topic>> GpSearchTechTopics(int start = 0, int count = 20)
        {
            return await GpSearchTopics(TechTopicsUrl, start, count);
        }

        public static async Task<IEnumerable<Topic>> GpsearchMyTopics(int start = 0, int count = 20)
        {
            var url = BuildUri(MyTopicsUrl);

            return JsonUtil.DeseriEnumerable<Topic>(await Search(url, bearer: true, start: start, count: count),
                "$.topics[*]");
        }


        public static async Task<IEnumerable<Group>> GpSearchExploreGroups(int start = 0, int count = 20)
        {
            return await GpSearchGroups(AllGroupsUrl, start, count);
        }

        public static async Task<IEnumerable<Group>> GpSearchCultureGroups(int start = 0, int count = 20)
        {
            return await GpSearchGroups(CultureGroupsUrl, start, count);
        }

        public static async Task<IEnumerable<Group>> GpSearchTravelGroups(int start = 0, int count = 20)
        {
            return await GpSearchGroups(TravelGroupsUrl, start, count);
        }

        public static async Task<IEnumerable<Group>> GpSearchEntGroups(int start = 0, int count = 20)
        {
            return await GpSearchGroups(EntGroupsUrl, start, count);
        }

        public static async Task<IEnumerable<Group>> GpSearchFashionGroups(int start = 0, int count = 20)
        {
            return await GpSearchGroups(FashionGroupsUrl, start, count);
        }

        public static async Task<IEnumerable<Group>> GpSearchLifeGroups(int start = 0, int count = 20)
        {
            return await GpSearchGroups(LifeGroupsUrl, start, count);
        }

        public static async Task<IEnumerable<Group>> GpSearchTechGroups(int start = 0, int count = 20)
        {
            return await GpSearchGroups(TechGroupsUrl, start, count);
        }

        public static async Task<IEnumerable<Comment>> GpSearchTopicComments(string topicId,int start = 0, int count = 20)
        {
            var url = BuildUri( string.Format(TopicCommentsUrl, topicId));

            return JsonUtil.DeseriEnumerable<Comment>(await Search(url, bearer: false, start: start, count: count),
                "$.comments[*]");
        }


        private static async Task<IEnumerable<Topic>> GpSearchTopics(string url, int start = 0, int count = 20)
        {
            url = BuildUri(url);

            return JsonUtil.DeseriEnumerable<Topic>(await Search(url, bearer: false, start: start, count: count),
                "$.topics..topic");
        }

        private static async Task<IEnumerable<Group>> GpSearchGroups(string url, int start = 0, int count = 20)
        {
            url = BuildUri(url);

            return JsonUtil.DeseriEnumerable<Group>(await Search(url, bearer: false, start: start, count: count),
                "$.groups[*]");
        }
    }
}
